#pragma once
#include <vector>
#include <string.h>
#include <string>
#include <algorithm>


// 网络库底层的缓冲区类型定义
/**
 * A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
 * +----------------------+---------------------+--------------------+
 * |   prependable bytes  |   readable bytes    |  writeable bytes
 * |                      |     (CONTENT)       |
 * +----------------------+---------------------+--------------------+
 * |                      |                     |                    |
 * 0           <=    readerIndex     <=    writerIndex       <=     size
 */
class Buffer
{
public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;

    explicit Buffer(size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend + initialSize)
        , readerIndex_(kCheapPrepend)
        , writerIndex_(kCheapPrepend)
        {}
    
    // ~Buffer();
    size_t readableBytes()  const { return writerIndex_ - readerIndex_;}
    size_t writeableBytes() const { return buffer_.size() - writerIndex_;}
    size_t prependableBytes() const { return readerIndex_; }
    //返回可读数据缓冲区的起始地址
    const char *peek() const {return begin() + readerIndex_;}
    // 
    void retrieve(size_t len) 
    {
        if(len < readableBytes())
        {
            readerIndex_ += len;//应用只读取了可读缓冲区数据的一部分，就是len
        }
        else
        {
            retrieveAll();
        }
    }
    void retrieveAll() 
    {
        readerIndex_ = kCheapPrepend;
        writerIndex_ = kCheapPrepend;
    }
    //把onMessage 函数上报的Buffer数据转成string类型的数据返回
    std::string retrieveAllAsString(){return retrieveAsString(readableBytes()); }
    std::string retrieveAsString(size_t len)
    { 
        std::string result(peek(),len);
        retrieve(len);// 上面一句把缓冲区中可读的数据，已经读取出来，这里对缓冲区进行复位
        return result;
    }
    void ensureWriteableBytes(size_t len)
    {
        if(writeableBytes() < len)
        {
            makeSpace(len);//扩容函数
        }
    }
    // 把data，data+len内存上的数据，添加到writeable缓冲区当中
    void append(const char* data,size_t len)
    {
        ensureWriteableBytes(len);
        std::copy(data,data+len,beginWrite());
        writerIndex_ += len;
    }
    char *beginWrite()
    { return begin() + writerIndex_; }

    const char* beginWrite() const
    { return begin() + writerIndex_; } 
    // 从fd上读取数据
    ssize_t readFd(int fd,int *savedErrno);
    
    ssize_t writeFd(int fd,int *savedErrno);

private:
    
    char *begin(){ return &*buffer_.begin();}//vector 底层数组首元素的地址，也就是数组的起始地址
    const char *begin() const { return &*buffer_.begin();}//vector 底层数组首元素的地址，也就是数组的起始地址
    void makeSpace(size_t len)
    {
        if(writeableBytes() + prependableBytes() < len + kCheapPrepend)
        {
            buffer_.resize(writerIndex_ + len);
        }
        else
        {
            size_t readable = readableBytes();
            std::copy(begin() + readerIndex_,
                    begin() + writerIndex_,
                    begin() + kCheapPrepend);
            readerIndex_ = kCheapPrepend;
            writerIndex_ = readerIndex_ + readable;
        }
    }    
    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writerIndex_;


};



